// Package middleware
/**
* @Project : geektime-basic-go-study
* @File    : login.go
* @IDE     : GoLand
* @Author  : Tvux
* @Date    : 2024/9/10 13:34
**/

package middleware

import (
	"github.com/HJH0924/GenericGo/set"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

type LoginMiddlewareBuilder struct {
	// 这里使用自己的另一个项目中所实现的set ^ ^
	ignorePaths *set.HashSet[string]
}

// NewLoginMiddlewareBuilder
// builder 模式 不能对用户的调用顺序有任何假设。
func NewLoginMiddlewareBuilder() *LoginMiddlewareBuilder {
	return &LoginMiddlewareBuilder{
		ignorePaths: set.NewHashSet[string](),
	}
}

func (Self *LoginMiddlewareBuilder) IgnorePath(path string) *LoginMiddlewareBuilder {
	Self.ignorePaths.Add(path)
	return Self
}

func (Self *LoginMiddlewareBuilder) Build() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		if Self.ignorePaths.Contains(ctx.Request.URL.Path) {
			// 不需要登录态校验
			return
		}
		session := sessions.Default(ctx)
		uid := session.Get("UserId")
		if uid == nil {
			// 没有登录
			ctx.AbortWithStatus(http.StatusUnauthorized)
			return
		}
		// 登录成功
		updateTime := session.Get("update_time")
		session.Set("UserId", uid) // 还需要放回去
		session.Options(sessions.Options{
			MaxAge: 60,
		})
		now := time.Now().UnixMilli()
		if updateTime == nil {
			// 第一次登录，还没有刷新，设置 update_time
			session.Set("update_time", now)
			if err := session.Save(); err != nil {
				panic(err)
			}
			return
		}

		// 判断是否刷新
		// 先断言一下
		updateTimeVal, ok := updateTime.(int64)
		if !ok {
			ctx.AbortWithStatus(http.StatusInternalServerError)
			return
		}
		if now-updateTimeVal > 60*1000 {
			// 超过了1分钟，就刷新
			session.Set("update_time", now)
			if err := session.Save(); err != nil {
				panic(err)
			}
			return
		}
	}
}

func (Self *LoginMiddlewareBuilder) CheckLogin() gin.HandlerFunc {
	return Self.IgnorePath("/users/signup").IgnorePath("/users/login").Build()
}
